
#include "libkfifo.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

struct kfifo *kfifo_init(char *buffer, unsigned int size) {
	struct kfifo *fifo;

	if(!is_power_of_2(size)) {
		printf("size must power of 2\n");
		return NULL;
	}
	fifo = (struct kfifo*)malloc(sizeof(struct kfifo));
	if(!fifo) {
		printf("failed to malloc memory");
		return NULL;
	}
	memset(fifo, 0, sizeof(struct kfifo));
	fifo->buffer = buffer;
	fifo->size = size;
	fifo->in = fifo->out = 0;
	return fifo;
}

struct kfifo *kfifo_alloc(unsigned int size) {
	char *buffer;
	struct kfifo *ret;

	if(!is_power_of_2(size)) {
		printf("size must power of 2\r\n");
		return NULL;
	}
	buffer = (char*)malloc(size);
	if(!buffer) {
		printf("malloc memory failed\r\n");
		return NULL;
	}
	ret = kfifo_init(buffer, size);
	if(!ret) {
		free(buffer);
		return NULL;
	}
	return ret;
}

void kfifo_free(struct kfifo *fifo) {
	if(fifo) {
		if(fifo->buffer) {
			free(fifo->buffer);
			fifo->buffer = NULL;
		}
		free(fifo);
		fifo = NULL;
	}
}

unsigned int kfifo_len(struct kfifo *fifo) {
	return fifo->in - fifo->out;
}

unsigned int kfifo_put(struct kfifo *fifo, char *buffer, unsigned int size) {
	unsigned int len = 0;

	size = min(size, fifo->size - fifo->in + fifo->out);
	len = min(size, fifo->size - (fifo->in & (fifo->size - 1)));
	memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, len);
	memcpy(fifo->buffer, buffer + len, size - len);
	fifo->in += size;
	return size;
}

unsigned int kfifo_get(struct kfifo *fifo, char *buffer, unsigned int size) {
	unsigned int len = 0;

	size = min(size, fifo->in - fifo->out);
	len = min(size, fifo->size - (fifo->out & (fifo->size - 1)));
	memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), len);
	memcpy(buffer + len, fifo->buffer, size - len);
	fifo->out += size;
	return size;
}




